<?php
// If $key == 'category' in any of the $where, it'll select both achievements and achievements_categories tables and match them on ID.
// If $key == 'short_name' in any of the $where, it'll select both achievements and achievements_earned tables and match them on ID. Value is optional, and is the value to match against short_name. Type needs to be correct (%s).
function dpa_get_unlocked( $what, $where=array(), $limit=0, $sort='', $debug=false ) {
	global $wpdb, $bp;
	
	$where_str = " WHERE ";
	$limit_str = '';
	$table_str = '';
	$sort_str  = '';
	$multple = false;
	$use_col = false;
	$use_var = false;
	$use_row = false;

	foreach ( (array) $where as $argument ) {

		if ( $multiple )
			$where_str .= ' AND ';

		$multiple = true;
		$type  = $argument['type'];
		$key   = $argument['key'];
		$value = $argument['value'];

		if ( $key == 'short_name' ) {

			$table_str .= ", {$bp->achievements->table_name}";
			$sql = "{$bp->achievements->table_name_unlocked}.achievement_id = {$bp->achievements->table_name}.id";			

			if ( !empty( $value ) ) {
			 	$sql .= " AND {$bp->achievements->table_name}.short_name = %{$type}";
				$where_str .= $wpdb->prepare( $sql, $value );
			} else {
				$where_str .= $wpdb->prepare( $sql );
			}
		} else if ( $key == 'category' ) {

			$table_str .= ", {$bp->achievements->table_name_categories}";			
			$where_str .= $wpdb->prepare( "{$bp->achievements->table_name_categories}.id = {$bp->achievements->table_name}.category_id AND {$bp->achievements->table_name_categories}.category = %s", $value );
		} else {

			$where_str .= $wpdb->prepare( "{$key} = %{$type}", $value );			
		}
	}

	if ( $where_str == " WHERE " )
		$where_str = '';

	if ( $limit > 0 )
		$limit_str = " LIMIT {$limit}";

	if ( 1 == $limit ) {
		$use_col = false;
		$use_var = false;
		$use_row = true;
	}

	if ( false === strpos( $what, ',' ) && false === strpos( $what, '*' ) ) {
		$use_col = true;
		$use_var = false;
		$use_row = false;
	}

	if ( false !== strpos( $what, 'COUNT' ) || ( 1 == $limit && false === strpos( $what, ',' ) && false === strpos( $what, '*' ) ) ) {
		$use_col = false;
		$use_var = true;
		$use_row = false;
	}
	
	if ( $sort != '' )
		$sort_str = " ORDER BY {$sort}";
		
	$query = "SELECT {$what} FROM {$bp->achievements->table_name_unlocked}{$table_str}" . $where_str . $sort_str . $limit_str;
	
	if ( $debug )
		die( $query );

	if ( $use_col ) {
		return $wpdb->get_col( $query );
	} else if ( $use_var ) {
		return $wpdb->get_var( $query );
	} else if ( $use_row ) {
		return $wpdb->get_row( $query, 'ARRAY_A' );
	} else {
		return $wpdb->get_results( $query, 'ARRAY_A' );		
	}	
}

// If $key == 'category' in any of the $where, it'll select both achievements and achievements_categories tables and match them on ID.
// If $what == '*', it'll select the achievements_categories tables and match them on ID.
function dpa_get( $what, $where=array(), $limit=0, $sort='', $debug=false ) {
	global $wpdb, $bp;
	
	$where_str = " WHERE ";
	$limit_str = '';
	$table_str = '';
	$sort_str = '';
	$multple = false;
	$use_col = false;
	$use_var = false;
	$use_row = false;

	foreach ( (array) $where as $argument ) {

		if ( $multiple )
			$where_str .= ' AND ';

		$multiple = true;
		$type  = $argument['type'];
		$key   = $argument['key'];
		$value = $argument['value'];

		if ( $key == 'category' ) {
			$table_str = ", {$bp->achievements->table_name_categories}";
			$where_str .= $wpdb->prepare( "{$bp->achievements->table_name_categories}.id = {$bp->achievements->table_name}.category_id AND {$bp->achievements->table_name_categories}.category = %s", $value );
		} else {
			$where_str .= $wpdb->prepare( "{$key} = %{$type}", $value );
		}
	}

	if ( false !== strpos( $what, 'category' ) ) {  // i.e. "DISTINCT category"
		$table_str .= ", {$bp->achievements->table_name_categories}";

		if ( $where_str != " WHERE " )
			$where_str .= ' AND ';

		$where_str .= "{$bp->achievements->table_name_categories}.id = {$bp->achievements->table_name}.category_id";
	}

	if ( '*' == $what ) {
		if ( false === strpos( $table_str, $bp->achievements->table_name_categories ) )
			$table_str = ", {$bp->achievements->table_name_categories}";

		if ( $where_str != " WHERE " )
			$where_str .= ' AND ';

		$where_str .= "{$bp->achievements->table_name_categories}.id = {$bp->achievements->table_name}.category_id";
	}

	if ( $where_str == " WHERE " )
		$where_str = '';

	if ( $limit > 0 )
		$limit_str = " LIMIT {$limit}";

	if ( 1 == $limit ) {
		$use_col = false;
		$use_var = false;
		$use_row = true;
	}

	if ( false === strpos( $what, ',' ) && false === strpos( $what, '*' ) ) {
		$use_col = true;
		$use_var = false;
		$use_row = false;
	}

	if ( false !== strpos( $what, 'COUNT' ) || ( 1 == $limit && false === strpos( $what, ',' ) && false === strpos( $what, '*' ) ) ) {
		$use_col = false;
		$use_var = true;
		$use_row = false;
	}

	if ( $sort != '' )
		$sort_str = " ORDER BY {$sort}";

	$query = "SELECT {$what} FROM {$bp->achievements->table_name}{$table_str}" . $where_str . $sort_str . $limit_str;

	if ( $debug )
		die( $query );

	if ( $use_col ) {
		return $wpdb->get_col( $query );
	} else if ( $use_var ) {
		return $wpdb->get_var( $query );
	} else if ( $use_row ) {
		return $wpdb->get_row( $query, 'ARRAY_A' );
	} else {
		return $wpdb->get_results( $query, 'ARRAY_A' );		
	}
}

function dpa_get_count_of_ea( $user_id, $category='' ) {
	$query = array( array( 'type' => 'd', 'key' => 'user_id', 'value' => $user_id ), array( 'type' => 'd', 'key' => 'active', 'value' => 1 ), array( 'type' => 's', 'key' => 'short_name', 'value' => '' ) );

	if ( '' != $category )
		$query[] = array( 'type' => 's', 'key' => 'category', 'value' => $category );

	return dpa_get_unlocked( 'COUNT(short_name)', $query) ;
}

function dpa_get_unlocked_details( $user_id, $achievement_name ) {
	return dpa_get_unlocked( '*', array( array( 'type' => 'd', 'key' => 'user_id', 'value' => $user_id ), array( 'type' => 's', 'key' => 'short_name', 'value' => $achievement_name ) ), 1 );
}

function dpa_update_usermeta( $user_id, $points=0 ) {
	$oldpoints = get_usermeta( $user_id, 'dpa_points' );
	update_usermeta( $user_id, 'dpa_points', apply_filters( 'dpa_filter_usermeta_points', $oldpoints ) + $points );
}

class dpa_achievement {
	var $user_id;       // user id
	var $name;          // achievement identifier
	var $is_unlocked;   // if this achievement has been unlocked
	var $points;				// points rewarded
	var $counter;       // counter (used to count things)
	
	function dpa_achievement( $args ) {
		$this->_populate( $args );
	}


	/**
	 * Protected functions
	 */
	function _populate( $args ) {
		$counter = false;
		extract( $args );

		$this->user_id      = $user_id;
		$this->name         = $name;
		$this->is_unlocked  = $this->_get_unlocked();
		$this->points       = $this->_get_points();

		if ( $counter )
			$this->counter      = $this->_get_counter();
	}
	
	function _get_counter() {
		$result = get_usermeta( $this->user_id, 'dpa_' . $this->name . '_counter' );
		if ( empty( $result ) )
			$result = 0;
		
		return $result;
	}
	
	function _get_unlocked() {
		$result = dpa_get_unlocked( 'achieved_at', array( array( 'type' => 'd', 'key' => 'user_id', 'value' => $this->user_id ), array( 'type' => 's', 'key' => 'short_name', 'value' => $this->name ) ), 1 );
		return !empty( $result );
	}
	
	function _get_points() {
		return dpa_get( 'points', array( array( 'type' => 's', 'key' => 'short_name', 'value' => $this->name ) ), 1 );
	}

	/**
	 * Public functions
	 */
	function unlock_achievement( $send_notification=true ) {
		global $bp, $wpdb;

		if ( $this->is_unlocked() )
			return;

		do_action( 'dpa_unlock_achievement', $this->user_id, $this->name, $this->points );	

		$achievement_id = dpa_get( 'id', array( array( 'type' => 's', 'key' => 'short_name', 'value' => $this->name ) ), 1 );
		$wpdb->insert( $bp->achievements->table_name_unlocked, array( 'achievement_id' => $achievement_id, 'user_id' => $this->user_id, 'achieved_at' => current_time( 'mysql' ) ) );

		if ( $send_notification ) {
			bp_core_add_notification( $achievement_id, $this->user_id, 'achievements', 'new_achievement', $this->user_id );
			dpa_record_activity( 
				array(
					'item_id' => $achievement_id,
					'user_id' => $this->user_id,
					'component_name' => $bp->achievements->slug,
					'component_action' => 'new_achievement', 
					'is_private' => 0
				)
			);

		  do_action( 'dpa_unlock_achievement_notification', $this->user_id, $this->name );
    }

		dpa_update_usermeta( $this->user_id, $this->points );
	}

	function is_unlocked() {
		return ( $this->is_unlocked );
	}

	function increment_counter( $i = 1 ) {
		$this->counter += $i;
		return update_usermeta( $this->user_id, 'dpa_' . $this->name . '_counter',  $this->counter ); 
	}
}
?>